/**
 @ Name：layui.cron Cron表达式解析器
 @ Author：贝哥哥
 @ License：MIT
 */

layui.define(['lay', 'element', 'form'], function (exports) { //假如该组件依赖 layui.form
  var $ = layui.$
    , layer = layui.layer
    , lay = layui.lay
    , element = layui.element
    , form = layui.form


    //字符常量
    , MOD_NAME = 'cron', ELEM = '.layui-cron', THIS = 'layui-this', SHOW = 'layui-show', HIDE = 'layui-hide'

    , ELEM_STATIC = 'layui-cron-static', ELEM_FOOTER = 'layui-cron-footer', ELEM_CONFIRM = '.cron-btns-confirm', ELEM_HINT = 'layui-cron-hint'

    , ELEM_RUN_HINT = 'layui-cron-run-hint'

    //外部接口
    , cron = {
      v: '2.0.1' // cron 组件当前版本
      , index: layui.cron ? (layui.cron.index + 10000) : 0 // corn 实例标识

      //设置全局项
      , set: function (options) {
        var that = this;
        that.config = $.extend({}, that.config, options);
        return that;
      }

      //事件监听
      , on: function (events, callback) {
        return layui.onevent.call(this, MOD_NAME, events, callback);
      }

      //主体CSS等待事件
      , ready: function (fn) {
        var cssPath = layui.cache.base + "cron/cron.css?v=" + cron.v;
        layui.link(cssPath, fn, "cron"); //此处的“cron”要对应 cron.css 中的样式： html #layuicss-cron{}
        return this;
      }
    }

    //操作当前实例
    , thisIns = function () {
      var that = this
        , options = that.config
        , id = options.id || options.index;

      return {
        //提示框
        hint: function (content) {
          that.hint.call(that, content);
        }
        , config: options
      }
    }

    //构造器，创建实例
    , Class = function (options) {
      var that = this;
      that.index = ++cron.index;
      that.config = $.extend({}, that.config, cron.config, options);
      cron.ready(function () {
        that.init();
      });
    };

  //默认配置
  Class.prototype.config = {
    value: null // 当前表达式值，每秒执行一次
    , isInitValue: true //用于控制是否自动向元素填充初始值（需配合 value 参数使用）
    , lang: "cn" //语言，只支持cn/en，即中文和英文
    , tabs: [{ key: 'seconds', range: '0-59' }, { key: 'minutes', range: '0-59' }, { key: 'hours', range: '0-23' }, { key: 'days', range: '1-31' }, { key: 'months', range: '1-12' }, { key: 'weeks', range: '1-7' }, { key: 'years' }]
    , tabsKeys: ['seconds', 'minutes', 'hours', 'days', 'months', 'weeks', 'years']
    , defaultCron: { seconds: "*", minutes: "*", hours: "*", days: "*", months: "*", weeks: "?", years: "" }
    , trigger: "click" //呼出控件的事件
    , btns: ['run', 'confirm'] //右下角显示的按钮，会按照数组顺序排列
    , position: null //控件定位方式定位, 默认absolute，支持：fixed/absolute/static
    , zIndex: null //控件层叠顺序
    , show: false //是否直接显示，如果设置 true，则默认直接显示控件
    , showBottom: true //是否显示底部栏
    , done: null //控件选择完毕后的回调，点击运行/确定也均会触发
    , run: null // 最近运行时间接口
  };

  //多语言
  Class.prototype.lang = function () {
    var that = this
      , options = that.config
      , text = {
        cn: {
          tabs: [{ key: "seconds", title: "秒" }
            , { key: "minutes", title: "分" }
            , { key: "hours", title: "时" }
            , { key: "days", title: "日" }
            , { key: "months", title: "月" }
            , { key: "weeks", title: "周", rateBegin: "第", rateMid: "周的星期", rateEnd: "" }
            , { key: "years", title: "年" }]
          , every: "每"
          , unspecified: "不指定"
          , period: "周期"
          , periodFrom: "从"
          , rate: "按照"
          , rateBegin: "从"
          , rateMid: "开始，每"
          , rateEnd: "执行一次"
          , weekday: "工作日"
          , weekdayPrefix: "每月"
          , weekdaySuffix: "号最近的那个工作日"
          , lastday: "本月最后一日"
          , lastweek: "本月最后一个星期"
          , custom: "指定"
          , tools: {
            confirm: '确定'
            , run: '运行'
          }
          , formatError: ['Cron格式不合法', '<br>已为你重置']
        }
        , en: {
          tabs: [{ key: "seconds", title: "Seconds" }
            , { key: "minutes", title: "Minutes" }
            , { key: "hours", title: "Hours" }
            , { key: "days", title: "Days" }
            , { key: "months", title: "Months" }
            , { key: "weeks", title: "Weeks" }
            , { key: "years", title: "Years" }]
          , every: "Every "
          , unspecified: "Unspecified"
          , period: "Period"
          , periodFrom: "From"
          , rate: "According to"
          , rateBegin: "begin at"
          , rateMid: ", every"
          , rateEnd: " execute once"
          , weekday: "Weekday"
          , weekdayPrefix: "Every month at "
          , weekdaySuffix: "号最近的那个工作日"
          , lastday: "Last day of the month"
          , lastweek: "本月最后一个星期"
          , custom: "Custom"
          , tools: {
            confirm: 'Confirm'
            , run: 'Run'
          }
          , formatError: ['The cron format error', '<br>It has been reset']
        }
      };
    return text[options.lang] || text['cn'];
  };

  //初始准备
  Class.prototype.init = function () {
    var that = this
      , options = that.config
      , isStatic = options.position === 'static';

    options.elem = lay(options.elem);

    options.eventElem = lay(options.eventElem);

    if (!options.elem[0]) return;

    //如果不是input|textarea元素，则默认采用click事件
    if (!that.isInput(options.elem[0])) {
      if (options.trigger === 'focus') {
        options.trigger = 'click';
      }
    }

    // 设置渲染所绑定元素的唯一KEY
    if (!options.elem.attr('lay-key')) {
      options.elem.attr('lay-key', that.index);
      options.eventElem.attr('lay-key', that.index);
    }

    // 当前实例主面板ID
    that.elemID = 'layui-icon' + options.elem.attr('lay-key');

    //默认赋值
    if (options.value && options.isInitValue) {
      that.setValue(options.value);
    }
    if (!options.value) {
      options.value = options.elem[0].value || '';
    }
    var cronArr = options.value.split(' ');
    if (cronArr.length >= 6) {
      options.cron = {
        seconds: cronArr[0],
        minutes: cronArr[1],
        hours: cronArr[2],
        days: cronArr[3],
        months: cronArr[4],
        weeks: cronArr[5],
        years: "",
      };
    } else {
      options.cron = lay.extend({}, options.defaultCron);
    }


    if (options.show || isStatic) that.render();
    isStatic || that.events();


  };

  // 控件主体渲染
  Class.prototype.render = function () {
    var that = this
      , options = that.config
      , lang = that.lang()
      , isStatic = options.position === 'static'
      , tabsKeys = options.tabsKeys
      , tabFilter = 'cron-tab' + options.elem.attr('lay-key')
      //主面板
      , elem = that.elem = lay.elem('div', {
        id: that.elemID
        , 'class': [
          'layui-cron'
          , isStatic ? (' ' + ELEM_STATIC) : ''
        ].join('')
      })

      // tab 内容区域
      , elemTab = that.elemTab = lay.elem('div', {
        'class': 'layui-tab layui-tab-card',
        'lay-filter': tabFilter
      })
      , tabHead = lay.elem('ul', {
        'class': 'layui-tab-title'
      })
      , tabContent = lay.elem('div', {
        'class': 'layui-tab-content'
      })

      //底部区域
      , divFooter = that.footer = lay.elem('div', {
        'class': ELEM_FOOTER
      });

    if (options.zIndex) elem.style.zIndex = options.zIndex;

    // 生成tab 内容区域
    elemTab.appendChild(tabHead);
    elemTab.appendChild(tabContent);
    lay.each(lang.tabs, function (i, item) {
      var index = tabsKeys.indexOf(item.key);
      if (index < 0) {
        return;
      }

      // 表头
      var li = lay.elem('li', {
        'class': i === 0 ? THIS : "",
        'lay-id': i
      });
      li.innerHTML = item.title;
      tabHead.appendChild(li);

      // 表体
      tabContent.appendChild(that.getTabContentChildElem(item.key, index === 0));
    });

    // 主区域
    elemMain = that.elemMain = lay.elem('div', {
      'class': 'layui-cron-main'
    });
    elemMain.appendChild(elemTab);

    //生成底部栏
    lay(divFooter).html(function () {
      var html = [], btns = [];
      lay.each(options.btns, function (i, item) {
        var title = lang.tools[item] || 'btn';
        btns.push('<span lay-type="' + item + '" class="cron-btns-' + item + '">' + title + '</span>');
      });
      html.push('<div class="cron-footer-btns">' + btns.join('') + '</div>');
      return html.join('');
    }());

    //插入到主区域
    elem.appendChild(elemMain);

    options.showBottom && elem.appendChild(divFooter);


    //移除上一个控件
    that.remove(Class.thisElemCron);

    //如果是静态定位，则插入到指定的容器中，否则，插入到body
    isStatic ? options.elem.append(elem) : (
      document.body.appendChild(elem)
      , that.position()
    );

    that.checkCron();

    that.elemEvent(); // 主面板事件

    Class.thisElemCron = that.elemID;

    form.render();
  }

  // 渲染 tab 子控件
  Class.prototype.getTabContentChildElem = function (tabKey, tabIsVisible = false) {
    var that = this,
      options = that.config,
      tabItem = options.tabs.find(u => u.key === tabKey),
      tabItemKey = tabItem.key,
      lang = that.lang(),
      tabItemLang = lang.tabs.find(u => u.key === tabKey),
      cron = options.cron,
      formFilter = 'cronForm' + tabItemKey + options.elem.attr('lay-key')
      , data = function () {
        if (cron[tabItemKey].indexOf('-') != -1) {
          // 周期数据
          var arr = cron[tabItemKey].split('-');
          return {
            type: 'range',
            start: arr[0],
            end: arr[1]
          };
        }
        if (cron[tabItemKey].indexOf('/') != -1) {
          // 频率数据
          var arr = cron[tabItemKey].split('/');
          return {
            type: 'rate',
            begin: arr[0],
            rate: arr[1]
          };
        }
        if (cron[tabItemKey].indexOf(',') != -1 || /^\+?[0-9][0-9]*$/.test(cron[tabItemKey])) {
          // 按照指定执行
          var arr = cron[tabItemKey].split(',').map(Number);
          return {
            type: 'custom',
            values: arr
          };
        }
        if (cron[tabItemKey].indexOf('W') != -1) {
          // 最近的工作日
          var value = cron[tabItemKey].replace('W', '');
          return {
            type: 'weekday',
            value: value
          };
        }
        if (tabKey === "days" && cron[tabItemKey] === 'L') {
          // 本月最后一日
          return {
            type: 'lastday',
            value: 'L'
          };
        }
        if (tabKey === "weeks" && cron[tabItemKey].indexOf('L') != -1) {
          // 本月最后一个周 value
          var value = cron[tabItemKey].replace('L', '');
          return {
            type: 'lastweek',
            value: value
          };
        }
        if (cron[tabItemKey] === '*') {
          // 每次
          return {
            type: 'every',
            value: '*'
          };
        }
        if (cron[tabItemKey] === '?' || cron[tabItemKey] === undefined || cron[tabItemKey] === '') {
          // 不指定
          return {
            type: 'unspecified',
            value: cron[tabItemKey]
          };
        }
      }()
      , rangeData = function () {
        if (tabItem.range) {
          var arr = tabItem.range.split('-');
          return {
            min: parseInt(arr[0]),
            max: parseInt(arr[1])
          };
        }
      }();
    var elem = lay.elem('div', {
      'class': 'layui-tab-item layui-form ' + (tabIsVisible ? SHOW : "")
      , 'lay-filter': formFilter
    });

    // 每次
    elem.appendChild(function () {
      var everyRadio = lay.elem('input', {
        'name': tabItemKey + '[type]'
        , 'type': 'radio'
        , 'value': 'every'
        , 'title': lang.every + tabItemLang.title
      });
      if (data.type === 'every') {
        lay(everyRadio).attr('checked', true);
      }
      var everyDiv = lay.elem('div', {
        'class': 'cron-row'
      });
      everyDiv.appendChild(everyRadio);
      return everyDiv;
    }());

    // 不指定，从日开始
    if (tabKey !== "seconds" && tabKey !== "minutes" && tabKey !== "hours") {
      elem.appendChild(function () {
        var unspecifiedRadio = lay.elem('input', {
          'name': tabItemKey + '[type]'
          , 'type': 'radio'
          , 'value': 'unspecified'
          , 'title': lang.unspecified
        });
        if (data.type === 'unspecified') {
          lay(unspecifiedRadio).attr('checked', true);
        }
        var unspecifiedDiv = lay.elem('div', {
          'class': 'cron-row'
        });
        unspecifiedDiv.appendChild(unspecifiedRadio);
        return unspecifiedDiv;
      }());
    }

    // 周期
    var rangeChild = [function () {
      var rangeRadio = lay.elem('input', {
        'name': tabItemKey + '[type]'
        , 'type': 'radio'
        , 'value': 'range'
        , 'title': lang.period
      });
      if (data.type === 'range') {
        lay(rangeRadio).attr('checked', true);
      }
      return rangeRadio;
    }(), function () {
      var elem = lay.elem('div', {
        'class': 'cron-input-mid'
      });
      elem.innerHTML = lang.periodFrom;
      return elem;
    }(), function () {
      var elem = lay.elem('input', {
        'class': 'cron-input',
        'type': 'number',
        'name': 'rangeStart',
        'value': data.start || ''
      });
      return elem;
    }(), function () {
      var elem = lay.elem('div', {
        'class': 'cron-input-mid'
      });
      elem.innerHTML = '-';
      return elem;
    }(), function () {
      var elem = lay.elem('input', {
        'class': 'cron-input',
        'type': 'number',
        'name': 'rangeEnd',
        'value': data.end || ''
      });
      return elem;
    }(), function () {
      var elem = lay.elem('div', {
        'class': 'cron-input-mid'
      });
      elem.innerHTML = tabItemLang.title;
      return elem;
    }()]

      , rangeDiv = lay.elem('div', {
        'class': 'cron-row'
      });
    lay.each(rangeChild, function (i, item) {
      rangeDiv.appendChild(item);
    });
    if (tabItem.range) {
      var rangeTip = lay.elem('div', {
        'class': 'cron-tips'
      });
      rangeTip.innerHTML = ['(', tabItem.range, ')'].join('');
      rangeDiv.appendChild(rangeTip);
    }
    elem.appendChild(rangeDiv);

    // 频率,年没有
    if (tabKey !== "years") {
      var rateChild = [function () {
        var rateRadio = lay.elem('input', {
          'name': tabItemKey + '[type]'
          , 'type': 'radio'
          , 'value': 'rate'
          , 'title': lang.rate
        });
        if (data.type === 'rate') {
          lay(rateRadio).attr('checked', true);
        }
        return rateRadio;
      }(), function () {
        var elem = lay.elem('div', {
          'class': 'cron-input-mid'
        });
        elem.innerHTML = tabItemLang.rateBegin || lang.rateBegin;
        return elem;
      }(), function () {
        var elem = lay.elem('input', {
          'class': 'cron-input',
          'type': 'number',
          'name': 'begin',
          'value': data.begin || ''
        });
        return elem;
      }(), function () {
        var elem = lay.elem('div', {
          'class': 'cron-input-mid'
        });
        elem.innerHTML = tabItemLang.rateMid || (tabItemLang.title + lang.rateMid);
        return elem;
      }(), function () {
        var elem = lay.elem('input', {
          'class': 'cron-input',
          'type': 'number',
          'name': 'rate',
          'value': data.rate || ''
        });
        return elem;
      }(), function () {
        var elem = lay.elem('div', {
          'class': 'cron-input-mid'
        });
        elem.innerHTML = undefined != tabItemLang.rateEnd ? tabItemLang.rateEnd : (tabItemLang.title + lang.rateEnd);
        if (undefined != tabItemLang.rateEnd && tabItemLang.rateEnd === '') {
          lay(elem).addClass(HIDE);
        }
        return elem;
      }()]

        , rateDiv = lay.elem('div', {
          'class': 'cron-row'
        });
      lay.each(rateChild, function (i, item) {
        rateDiv.appendChild(item);
      });
      if (tabItem.range) {
        var rateTip = lay.elem('div', {
          'class': 'cron-tips'
        });
        if (tabKey === "weeks") {
          // 周
          rateTip.innerHTML = '(1-4/1-7)';
        } else {
          rateTip.innerHTML = ['(', rangeData.min, '/', (rangeData.max + ((tabKey === "seconds" || tabKey === "minutes" || tabKey === "hours") ? 1 : 0)), ')'].join('');
        }
        rateDiv.appendChild(rateTip);
      }
      elem.appendChild(rateDiv);
    }

    // 特殊：日（最近的工作日、最后一日），周（最后一周）
    if (tabKey === "days") {
      // 日
      // 最近的工作日
      var weekChild = [function () {
        var weekRadio = lay.elem('input', {
          'name': tabItemKey + '[type]'
          , 'type': 'radio'
          , 'value': 'weekday'
          , 'title': lang.weekday
        });
        if (data.type === 'weekday') {
          lay(weekRadio).attr('checked', true);
        }
        return weekRadio;
      }(), function () {
        var elem = lay.elem('div', {
          'class': 'cron-input-mid'
        });
        elem.innerHTML = lang.weekdayPrefix;
        return elem;
      }(), function () {
        var elem = lay.elem('input', {
          'class': 'cron-input',
          'type': 'number',
          'name': 'weekday',
          'value': data.value || ''
        });
        return elem;
      }(), function () {
        var elem = lay.elem('div', {
          'class': 'cron-input-mid'
        });
        elem.innerHTML = lang.weekdaySuffix;
        return elem;
      }(), function () {
        var elem = lay.elem('div', {
          'class': 'cron-tips'
        });
        elem.innerHTML = ['(', tabItem.range, ')'].join('');
        return elem;
      }()]

        , weekDiv = lay.elem('div', {
          'class': 'cron-row'
        });
      lay.each(weekChild, function (i, item) {
        weekDiv.appendChild(item);
      });
      elem.appendChild(weekDiv);

      // 本月最后一日
      elem.appendChild(function () {
        var lastRadio = lay.elem('input', {
          'name': tabItemKey + '[type]'
          , 'type': 'radio'
          , 'value': 'lastday'
          , 'title': lang.lastday
        });
        if (data.type === 'lastday') {
          lay(lastRadio).attr('checked', true);
        }
        var lastDiv = lay.elem('div', {
          'class': 'cron-row'
        });
        lastDiv.appendChild(lastRadio);
        return lastDiv;
      }());

    }

    if (tabKey === "weeks") {
      // 本月最后一个周几
      var lastWeekChild = [function () {
        var lastWeekRadio = lay.elem('input', {
          'name': tabItemKey + '[type]'
          , 'type': 'radio'
          , 'value': 'lastweek'
          , 'title': lang.lastweek
        });
        if (data.type === 'lastweek') {
          lay(lastWeekRadio).attr('checked', true);
        }
        return lastWeekRadio;
      }(), function () {
        var elem = lay.elem('input', {
          'class': 'cron-input',
          'type': 'number',
          'name': 'lastweek',
          'value': data.value || ''
        });
        return elem;
      }(), function () {
        var elem = lay.elem('div', {
          'class': 'cron-tips'
        });
        elem.innerHTML = ['(', tabItem.range, ')'].join('');
        return elem;
      }()]

        , lastWeekDiv = lay.elem('div', {
          'class': 'cron-row'
        });
      lay.each(lastWeekChild, function (i, item) {
        lastWeekDiv.appendChild(item);
      });
      elem.appendChild(lastWeekDiv);

    }

    // 指定
    if (tabKey !== "years") {
      elem.appendChild(function () {
        var customRadio = lay.elem('input', {
          'name': tabItemKey + '[type]'
          , 'type': 'radio'
          , 'value': 'custom'
          , 'title': lang.custom
        });
        if (data.type === 'custom') {
          lay(customRadio).attr('checked', true);
        }
        var customDiv = lay.elem('div', {
          'class': 'cron-row'
        });
        customDiv.appendChild(customRadio);
        return customDiv;
      }());

      // 指定数值，时分秒显示两位数，自动补零
      elem.appendChild(function () {
        var customGrid = lay.elem('div', {
          'class': 'cron-grid'
        });
        var i = rangeData.min;
        while (i <= rangeData.max) {
          // 时分秒显示两位数，自动补零
          var gridItemValue = (tabKey === "seconds" || tabKey === "minutes" || tabKey === "hours") ? lay.digit(i, 2) : i;
          var gridItem = lay.elem('input', {
            'type': 'checkbox',
            'title': gridItemValue,
            'lay-skin': 'primary',
            'name': tabItemKey + '[custom]',
            'value': i
          });
          if (data.values && data.values.includes(i)) {
            lay(gridItem).attr('checked', true);
          }
          customGrid.appendChild(gridItem);
          i++;
        }
        return customGrid;
      }());
    }


    return elem;
  }

  //是否输入框
  Class.prototype.isInput = function (elem) {
    return /input|textarea/.test(elem.tagName.toLocaleLowerCase());
  };

  // 绑定的元素事件处理
  Class.prototype.events = function () {
    var that = this
      , options = that.config

      //绑定呼出控件事件
      , showEvent = function (elem, bind) {
        elem.on(options.trigger, function () {
          bind && (that.bindElem = this);
          that.render();
        });
      };

    if (!options.elem[0] || options.elem[0].eventHandler) return;

    showEvent(options.elem, 'bind');
    showEvent(options.eventElem);

    //绑定关闭控件事件
    lay(document).on('click', function (e) {
      if (e.target === options.elem[0]
        || e.target === options.eventElem[0]
        || e.target === lay(options.closeStop)[0]) {
        return;
      }
      that.remove();
    }).on('keydown', function (e) {
      if (e.keyCode === 13) {
        if (lay('#' + that.elemID)[0] && that.elemID === Class.thisElemDate) {
          e.preventDefault();
          lay(that.footer).find(ELEM_CONFIRM)[0].click();
        }
      }
    });

    //自适应定位
    lay(window).on('resize', function () {
      if (!that.elem || !lay(ELEM)[0]) {
        return false;
      }
      that.position();
    });

    options.elem[0].eventHandler = true;
  };

  // 主面板事件
  Class.prototype.elemEvent = function () {
    var that = this
      , options = that.config
      , tabFilter = 'cron-tab' + options.elem.attr('lay-key');

    // 阻止主面板点击冒泡，避免因触发文档事件而关闭主面
    lay(that.elem).on('click', function (e) {
      lay.stope(e);
    });

    // tab选项卡切换
    var lis = lay(that.elemTab).find('li');
    lis.on('click', function () {
      var layid = lay(this).attr('lay-id');
      if (undefined === layid) {
        return;
      }
      element.tabChange(tabFilter, layid);
    });

    // cron选项点击
    form.on('radio', function (data) {
      var $parent = data.othis.parent();
      var formFilter = $parent.parent().attr('lay-filter');
      var formData = form.val(formFilter);
      var radioType = data.value;
      if ('range' === radioType) {
        // 范围
        form.val(formFilter, {
          rangeStart: formData.rangeStart || 0,
          rangeEnd: formData.rangeEnd || 2
        });
      }
      if ('rate' === radioType) {
        // 频率
        form.val(formFilter, {
          begin: formData.begin || 0,
          rate: formData.rate || 2
        });
      }
      if ('custom' === radioType) {
        // custom
        var $grid = $parent.next();
        if ($grid.find(':checkbox:checked').length <= 0) {
          $grid.children(':checkbox:first').next().click()
        }
      }
      if ('weekday' === radioType) {
        // weekday
        form.val(formFilter, {
          weekday: formData.weekday || 1
        });
      }
      if ('lastweek' === radioType) {
        // lastweek
        form.val(formFilter, {
          lastweek: formData.lastweek || 1
        });
      }

    });

    //点击底部按钮
    lay(that.footer).find('span').on('click', function () {
      var type = lay(this).attr('lay-type');
      that.tool(this, type);
    });
  };

  //底部按钮点击事件
  Class.prototype.tool = function (btn, type) {
    var that = this
      , options = that.config
      , lang = that.lang()
      , isStatic = options.position === 'static'
      , active = {
        //运行
        run: function () {
          var value = that.parse();
          var loading = layer.load();
          $.get(options.run, { cron: value }, function (res) {
            layer.close(loading);
            if (res.code !== 0) {
              return that.hint(res.msg);
            }
            that.runHint(res.data);
          }, 'json').fail(function () {
            layer.close(loading);
            that.hint('服务器异常！');
          });
        }

        //确定
        , confirm: function () {
          var value = that.parse();
          that.done([value]);
          that.setValue(value).remove()
        }
      };
    active[type] && active[type]();
  };

  //执行 done/change 回调
  Class.prototype.done = function (param, type) {
    var that = this
      , options = that.config;

    param = param || [that.parse()];
    typeof options[type || 'done'] === 'function' && options[type || 'done'].apply(options, param);

    return that;
  };

  // 解析cron表达式
  Class.prototype.parse = function () {
    var that = this
      , options = that.config
      , valueArr = [];

    lay.each(options.tabs, function (index, item) {
      var key = item.key;
      var formFilter = 'cronForm' + key + options.elem.attr('lay-key');
      var formData = form.val(formFilter);
      var radioType = (key + '[type]');
      var current = "*";
      if (formData[radioType] === 'every') {
        // 每次
        current = "*";
      }
      if (formData[radioType] === 'range') {
        // 范围
        current = formData.rangeStart + "-" + formData.rangeEnd;
      }
      if (formData[radioType] === 'rate') {
        // 频率
        current = formData.begin + "/" + formData.rate;
      }
      if (formData[radioType] === 'custom') {
        // 指定
        var checkboxName = (item.key + '[custom]');
        var customArr = [];
        $('input[name="' + checkboxName + '"]:checked').each(function () {
          customArr.push($(this).val());
        });
        current = customArr.join(',');
      }
      if (formData[radioType] === 'weekday') {
        // 每月 formData.weekday 号最近的那个工作日
        current = formData.weekday + "W";
      }
      if (formData[radioType] === 'lastday') {
        // 本月最后一日
        current = "L";
      }
      if (formData[radioType] === 'lastweek') {
        // 本月最后星期 
        current = formData.lastweek + "L";
      }

      if (formData[radioType] === 'unspecified' && index != 6) {
        // 不指定
        current = "?";
      }

      if (current !== "") {
        valueArr.push(current);
        options.cron[key] = current;
      }
    });
    return valueArr.join(' ');
  };

  //控件移除
  Class.prototype.remove = function (prev) {
    var that = this
      , options = that.config
      , elem = lay('#' + (prev || that.elemID));
    if (!elem[0]) return that;

    if (!elem.hasClass(ELEM_STATIC)) {
      that.checkCron(function () {
        elem.remove();
      });
    }
    return that;
  };

  //定位算法
  Class.prototype.position = function () {
    var that = this
      , options = that.config;
    lay.position(that.bindElem || options.elem[0], that.elem, {
      position: options.position
    });
    return that;
  };

  //提示
  Class.prototype.hint = function (content) {
    var that = this
      , options = that.config
      , div = lay.elem('div', {
        'class': ELEM_HINT
      });

    if (!that.elem) return;

    div.innerHTML = content || '';
    lay(that.elem).find('.' + ELEM_HINT).remove();
    that.elem.appendChild(div);

    clearTimeout(that.hinTimer);
    that.hinTimer = setTimeout(function () {
      lay(that.elem).find('.' + ELEM_HINT).remove();
    }, 3000);
  };

  //运行提示
  Class.prototype.runHint = function (runList) {
    var that = this
      , options = that.config
      , div = lay.elem('div', {
        'class': ELEM_RUN_HINT
      });
    // debugger;
    if (!that.elem || !runList || !runList.length) return;


    lay(div).html(function () {
      var html = [];
      lay.each(runList, function (i, item) {
        html.push('<div class="cron-run-list">' + item + '</div>');
      });
      return html.join('');
    }());

    lay(that.elem).find('.' + ELEM_RUN_HINT).remove();
    that.elem.appendChild(div);
  };

  //赋值
  Class.prototype.setValue = function (value = '') {
    var that = this
      , options = that.config
      , elem = that.bindElem || options.elem[0]
      , valType = that.isInput(elem) ? 'val' : 'html'

    options.position === 'static' || lay(elem)[valType](value || '');

    return this;
  };

  //cron校验
  Class.prototype.checkCron = function (fn) {
    var that = this
      , options = that.config
      , lang = that.lang()
      , elem = that.bindElem || options.elem[0]
      , value = that.isInput(elem) ? elem.value : (options.position === 'static' ? '' : elem.innerHTML)

      , checkValid = function (value = "") {

      };

    // cron 值，多个空格替换为一个空格，去掉首尾空格
    value = value || options.value;
    if (typeof value === 'string') {
      value = value.replace(/\s+/g, ' ').replace(/^\s|\s$/g, '');
    }

    if (fn === 'init') return checkValid(value), that;

    value = that.parse();
    if (value) {
      that.setValue(value);
    }
    fn && fn();
    return that;
  };

  //核心入口
  cron.render = function (options) {
    var ins = new Class(options);
    return thisIns.call(ins);
  };

  exports('cron', cron);
});